﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using RAE.Logica.Info;
using RAE.Logica.Torneos;
using System.Text.RegularExpressions;
using RAE.Persistencia;

namespace RAE.Logica.Controladores
{
    class CalculadorElo
    {
        private static double obtenerPuntajeEsperado(Ajedrecista a, Ajedrecista b) {
            double diff = (b.puntaje_elo - a.puntaje_elo) / 400.0;
            return 1 / (1.0 + Math.Pow(10.0, diff));
        }

        private static KeyValuePair<int,int>? parsearResultado(string resultado_ronda)
        {
            Regex r = new Regex("([0-9]+)[wb](0|1|/)");
            Match match = r.Match(resultado_ronda);
            if (match.Success)
            {
                int indice = Int32.Parse(match.Groups[1].Value) - 1;

                switch (match.Groups[2].Value)
                {
                    case "0":
                        return new KeyValuePair<int,int>(indice,0);
                    case "/":
                        return new KeyValuePair<int,int>(indice,1);;
                    case "1":
                        return new KeyValuePair<int,int>(indice,2);;
                    default:
                        return new KeyValuePair<int,int>(indice,0);;
                }
            }
            else
                return null;
        }

        public static void actualizarPuntajesElo(Torneo t)
        {
            foreach (FilaCrosstable fila in t.crosstable) 
            {
                Ajedrecista a = fila.ajedrecista;
                double puntaje = 0.0;

                foreach (string raw in fila.resultados)
                {
                    KeyValuePair<int, int>? resultado = parsearResultado(raw);

                    if (resultado.HasValue)
                    {
                        Ajedrecista b = t.ajedrecistas[resultado.Value.Key];
                        puntaje = puntaje + (resultado.Value.Value / 2.0) - obtenerPuntajeEsperado(a, b);
                    }
                }

                a.puntaje_elo += (int) Math.Round(a.categoria.coeficiente * puntaje);

                if (a.puntaje_elo < Aplicacion.puntaje_elo_min)
                    a.puntaje_elo = Aplicacion.puntaje_elo_min;

                Cargador.actualizarElo(a);
            }
        }
    }
}
